package ca.magex.gps.entity.impl;

import java.util.ArrayList;
import java.util.List;

import ca.magex.gps.entity.LatLongPoint;
import ca.magex.gps.entity.Trackpoint;
import ca.magex.gps.entity.TrackpointContainer;
import ca.magex.gps.entity.XYPoint;

public class TrackpointContainerImpl extends PersistentObject implements TrackpointContainer {

	private List<Trackpoint> trackpoints;
	
	private double marginTop = Double.NaN;
	private double marginRight = Double.NaN;
	private double marginBottom = Double.NaN;
	private double marginLeft = Double.NaN;
	
	private boolean marginInitialized = false;
	
	public TrackpointContainerImpl() {
		trackpoints = new ArrayList<Trackpoint>();
	}
	
	public void addTrackpoint(Trackpoint tp) {
		trackpoints.add(tp);
		if (!marginInitialized) {
			marginTop = tp.getLongitude();
			marginBottom = tp.getLongitude();
			marginRight = tp.getLatitude();
			marginLeft = tp.getLatitude();
			marginInitialized = true;
		}
		if (tp.getLongitude() < marginBottom) marginBottom = tp.getLongitude();
		if (tp.getLongitude() > marginTop) marginTop = tp.getLongitude();
		if (tp.getLatitude() < marginLeft) marginLeft = tp.getLatitude();
		if (tp.getLatitude() > marginRight) marginRight = tp.getLatitude();
	}
	
	public List<Trackpoint> getTrackpoints() {
		return trackpoints;
	}

	public List<Trackpoint> getTrackpoints(int limit) {
		List<Trackpoint> ret = new ArrayList<Trackpoint>();
		List<Trackpoint> trackpoints = getTrackpoints();
		int interval = (int)Math.ceil(trackpoints.size() / limit);
		for (int i = 0; i < trackpoints.size(); i += interval) {
			ret.add(trackpoints.get(i));
		}
		return ret;
	}

	public double getWidth() {
		return marginRight - marginLeft;
	}

	public double getHeight() {
		return marginTop - marginBottom;
	}

	public LatLongPoint getCenter() {
		return new LatLongPointImpl(marginLeft + (getWidth() / 2), marginBottom + (getHeight() / 2));
	}

	public LatLongPoint getNorthWest() {
		return new LatLongPointImpl(marginLeft, marginTop);
	}

	public LatLongPoint getSouthEast() {
		return new LatLongPointImpl(marginRight, marginBottom);
	}

	public List<XYPoint> getNormailzedPoints(int size) {
		List<XYPoint> ret = new ArrayList<XYPoint>();
		double factor = getWidth() < getHeight() ? size / getHeight() : size / getWidth();
		double width = getWidth() * factor;
		double height = getHeight() * factor;
		for (Trackpoint tp : getTrackpoints()) {
			double x = ((tp.getLatitude() - getNorthWest().getLatitude()) * factor);
			double y = ((tp.getLongitude() - getSouthEast().getLongitude()) * factor);
			if (x < 0 || x > width)
				throw new IllegalStateException("ERROR: x is too big from trackpoint: " + tp);
			if (y < 0 || y > height)
				throw new IllegalStateException("ERROR: y is too big from trackpoint: " + tp);
			x += (size - width) / 2;
			y += (size - height) / 2;
			ret.add(new XYPointImpl(x, y));
		}
		return ret;
	}

}
